## You need the following if this is ever being run as a script 
import os, sys  
  
sys.path.insert(0, "C:\Documents and Settings\wendy_admin\src\eclipse_workspace\djangodb\main")  
if not os.environ.has_key("DJANGO_SETTINGS_MODULE"):
    os.environ["DJANGO_SETTINGS_MODULE"]="wjContact.settings"
    
import datetime
import pdb

from django import newforms as forms

## This is for the check_for_duplicates method. Should consider refactoring
## this, to keep views type stuff out of this forms file.
from django.shortcuts import render_to_response

from wjContact.contacts.constants import MSG_CODES, DEFAULT_LISTSIZE

from wjContact.contacts.models import Phone, ContactPhone, NewPhone
from wjContact.contacts.models import Contact, Recipient, Volunteer
from wjContact.contacts.models import GroupService, Group
from wjContact.contacts.models import Language, UserLanguage
from wjContact.contacts.models import Pet, Middlename


from wjContact.contacts.views.fields import PetField, NewPhoneField
from wjContact.contacts.views.fields import FieldList 
from wjContact.contacts.views.widgets import PetWidget, PhoneWidget

from django.newforms.forms import SortedDictFromList

    


##============================================================================##
## Multi-table forms
## -----------------
## There are two things you need to do to make a form which can save data to
## more than one table.
## 1. Add all the fields from each of the tables to the form.
## 2. Over-ride the 'save()' method of the form so that it correctly saves the 
##    data from each of these fields into the right table. This requires some
##    care when there are foreign-key relations between the tables (which there
##    usually are). 
##
## For instance, to completely save a 'Contact' database entry,
## you need to first save the general contact details to the 'Contact' table
## (first_name, last_name, address, suburb, state, country, email, and 
## date_added). You do this by making a 'contact' object and calling save() on 
## it. Then you need to make one or more PhoneNumber entries in the PhoneNumber
## table, using the data entered in the phone number-related widgets. 
## Finally, you need to make an  entry in the ContactPhone joining table to
## connect the PhoneNumber entries with the Contact Entry.
##
## To make a 'Recipient' database entry, you need to do all of the above, and 
## then correctly save the Recipient-Specific details (stay-with-linux, 
## has-used-computer-before, and so on). Finally you need to make some 
## Language entries and correctly join these to the Recipient.
##
## At the moment, the below is pretty messy - still just trying things out.
## Some obvious stuff that needs fixing (just the start of a long list!):
## ** re-do the RecipientForm class, so that there is not as much 
##    overlap with stuff that the ContactForm already does. [done - they now 
##    inherit the overlapping stuff from ContactForm, ie the fields that exist
##    on both. And they call the ContactForm save() method before doing their
##    own specific save() stuff.]
## ** redo addAllContactView, and the various 'handle' views to reduce overlap
## 
## 
## ===========================================================================##

        
class DeclarativeExtensibleFormMetaclass(type):
    """
    Metaclass that converts Field attributes to a dictionary called
    'base_fields', taking into account parent class 'base_fields' as well.
    """
    #from forms.fields import Field
    #from django.newforms.fields import Field
    
    def __new__(cls, name, bases, attrs):
        Field = forms.Field
        ## field_series will hold a list of 
        ## (name, recurrent_field_array) pairs
        fieldlists = [
                (key, attrs.pop(key)) for key, obj in attrs.items() 
                if isinstance(obj, FieldList)
                ]
        ## We need klass to be the class of the 'main' object that this form is 
        ## all about - ie a Contact or a Recipient or whatever.
        ## There had better only be one of these - kludgey!   XXX FIXME
#        klasses = [
#                (key, attrs.pop(key)) for key, obj in attrs.items() 
#                if (type(obj) == 'type')
#                ]
#        attrs['klass'] = klasses[0]
        ## Put fieldlists into attrs so that it will be available to 
        ## instances
        attrs['fieldlists'] = fieldlists
        for (fieldlist_name, fieldlist) in fieldlists:
            ## next line sets up 'form.pets=RecurringField(whatever)'
            attrs[fieldlist_name] = fieldlist
           
        fields = [(field_name, attrs.pop(field_name)) for field_name, obj in attrs.items() if isinstance(obj, Field)]

        ## May need think about the creation counter in the copies at some 
        ## point (see definiton of FieldList).
        fields.sort(lambda x, y: cmp(x[1].creation_counter, y[1].creation_counter))
        
        # If this class is subclassing another Form, add that Form's fields.
        # Note that we loop over the bases in *reverse*. This is necessary in
        # order to preserve the correct order of fields.
        for base in bases[::-1]:
            if hasattr(base, 'base_fields'):
                fields = base.base_fields.items() + fields

        attrs['base_fields'] = SortedDictFromList(fields)
        return type.__new__(cls, name, bases, attrs)

class ExtensibleForm(forms.BaseForm):
    """
    Usage Notes: In the template, the form.pets variable and the 
    'add_another_pet' input must be named correctly 
    """
    # This is a separate class from BaseForm in order to abstract the way
    # self.fields is specified. This class (Form) is the one that does the
    # fancy metaclass stuff purely for the semantic sugar -- it allows one
    # to define a form using declarative syntax.
    # BaseForm itself has no way of designating self.fields.
    __metaclass__ = DeclarativeExtensibleFormMetaclass
    
    def __init__(self, *args, **kwargs):
        """  """      
        ## I think that what is happening is that the build_repeaters() call
        ## from the view (when adding more pets) is over-writing the earlier 
        ## one from this __init__...What we want is,  __init__ to automatically
        ## build itself up from *either* data *or* initial, whichever is 
        ## supplied.
        ## Then,after that, we want to add more field(s) in a non-destructive 
        ## way,not wiping over what has already been done. 
        touched_initialised_add_form  = ('initial' in kwargs) and not ('main_object' in kwargs)
        touched_initialised_edit_form  = ('initial' in kwargs) and ('main_object' in kwargs)
        touched_add_form  = args and not ('main_object' in kwargs)
        touched_edit_form = args and ('main_object' in kwargs)   
        fresh_add_form    = (not args) and not ('main_object' in kwargs)
        fresh_edit_form   = (not args) and ('main_object' in kwargs) and not ('initial' in kwargs)
         
        ## If we have been passed an owner_id, we are going to stick the 
        ## existing data for that owner_id into our fields. Stick this on as
        ## an attribute in self, so we can get to it everywhere :)
        ## Pop it rather than just getting it, to remove these keywords from the 
        ## kwargs dict or else forms.Form.__init__ will be unhappy.
       
        self.main_object = kwargs.pop('main_object', None)
        
        if fresh_edit_form:
            self.stage_type = 'fresh_edit'
            owner = self.main_object
            ## If this is an edit_form, we need to get out the existing database
            ## records and display them. Thus far we have the database ids for 
            ## the 'main entity' that this form is about (Contact, Owner, 
            ## whatever)
            ## Get out the names and values of the model fields, and put them 
            ## into our kwargs with the key 'data'. When we go through the 
            ## __init__
            ## from the superclass, these will become the data variable passed
            ## in to create a Bound form.
            model_fieldnames = [field.name for field in owner._meta.fields]
            model_fieldvalues = [owner.__getattribute__(fieldname) for 
                fieldname in model_fieldnames]      
            data_dict=dict(zip(model_fieldnames, model_fieldvalues))
            kwargs['initial'] = data_dict
        elif touched_edit_form:
            ## This is case 2
            self.stage_type = 'touched_edit'
            ## Don't need to do anything, I think - we have the data we need
            ## in  our args (from request.POST), and when we later go to save()
            ## we have a self.name_id also.
            pass
        elif fresh_add_form:
            self.stage_type = 'fresh_add'
            ## We currently do nothing for fresh_add forms - but here is a hook
            ## where we could if we wanted - ie if we wanted to change the 
            ## default values displayed or something.
            pass
        elif touched_add_form:
            self.stage_type = 'touched_add'
            ## We currently do nothing for touched_add forms - all the 
            ## necessary data is in args already, but here is a 
            ## hook where we could if we wanted.
            pass
        if touched_initialised_add_form:
            self.stage_type = 'touched_initialised_add'
        if touched_initialised_edit_form:
            self.stage_type = 'touched_initialised_edit'
        ## Now we are ready to call BaseForm.__init__    
        forms.BaseForm.__init__(self, *args, **kwargs)
        self.build_repeaters()
       
        
    def put_fieldlists_into_form_fields(self):    
        ## first build-up the fieldlists inside the field-sequences
        ##fs will be a tuple of (name, FieldList) ie
        ## ('pets', 
        ## <wjContact.contacts.views.fields.FieldList object at 0x016218B0>)              
        ## base_name is the 'root name' for all the fields in this 
        ## field-list, ie phone for phones, pet for pets, etc  
        ## So how_many tells us how many fields there need to be in
        ## this field-list to hold the info for the entries which
        ## already exist in the form-data (or in form.initial).              
#        for fs in self.fieldlists:
#                how_many=len(self.get_names_from_datadict(fs[1].base_name))         
        ## And then deal with getting them all into self.fields       
        all_fields_from_fieldlists = []
        for fl in self.fieldlists:  
            ## Now set up the *individual* fields that should end up in
            ## self.fields.       
            all_fields_from_fieldlists.extend(fl[1].get_names_and_fields())
        ## all_fields_from_sequences is now a list of pairs of (key, value),
        ## but we need a dict:
        all_fields_from_fieldlists_as_dict = dict(all_fields_from_fieldlists)
        ## update self.fields. The update() method over-writes existing entries
        ## with the same key, but this shouldn't be a problem since we have
        ## given all of the new fields a numerical suffix, ie pet_0, pet_1
        ## Also, we never should have tried to have another field named 'pet' 
        ## anyway!
        self.fields.update(all_fields_from_fieldlists_as_dict)
            
    def build_repeaters(self):
        if self.stage_type == 'fresh_add': 
            """Can combine this with one of the other conditionals """ 
            ## first build-up the fieldlists inside the field-sequences
            for dummy, fieldlist in self.fieldlists:
                ## fs will be a tuple of (name, FieldList) ie
                ## ('pets', 
                ## <wjContact.contacts.views.fields.FieldList object at 0x016218B0>)
                fieldlist.build_fields(number=1)
                ## Also give each one a reference to the formn  they are on, so
                ## that when they are needing to Bind, they can
                fieldlist.set_form(self)   
            ## And then deal with getting them all into self.fields 
            self.put_fieldlists_into_form_fields()      

        if  (self.stage_type == 'touched_initialised_edit') or (self.stage_type
             == 'touched_initialised_add'):
            """Can combine this with one of the other conditionals """ 
            ## first build-up the fieldlists inside the field-sequences         
            for dummy, fieldlist in self.fieldlists:
                ## fs will be a tuple of (name, FieldList) ie
                ## ('pets', 
                ## <wjContact.contacts.views.fields.FieldList object at 0x016218B0>)              
                ## base_name is the 'base name' for this recurring field, ie 
                ## phone for phones, pet for pets, etc                
                how_many=len(self.get_names_from_datadict(fieldlist.base_name))
                fieldlist.build_fields(how_many)
                ## Also give each one a reference to the form  they are on, so
                ## that when they are needing to Bind, they can do so.
                fieldlist.set_form(self)  
               
            ## And then deal with getting them all into self.fields 
            self.put_fieldlists_into_form_fields()       
            
        if (self.stage_type == 'touched_add') or (self.stage_type == 
            'touched_edit'): 
            ## first build-up the fieldlists inside the field-sequences
            for dummy, fieldlist in self.fieldlists:
                ## fs will be a tuple of (name, FieldList) ie
                ## ('pets', 
                ## <wjContact.contacts.views.fields.FieldList object at 0x016218B0>)              
                ## base_name is the 'base name' for this recurring field, ie 
                ## phone for phones, pet for pets, etc                
                how_many=len(self.get_names_from_datadict(fieldlist.base_name))
                fieldlist.build_fields(how_many)
                ## Also give each one a reference to the form  they are on, so
                ## that when they are needing to Bind, they can do so.
                fieldlist.set_form(self)  

            ## And then deal with getting them all into self.fields  
            self.put_fieldlists_into_form_fields()      
           
        if self.stage_type == 'fresh_edit': 
            """Subclasses will implement """
            """ Or if not using subclasses to implement, try using
                form.initial as a whole rather than populating the individual 
                fields perhaps?"""
            ## If we are 'fresh', we need to get the relevant data out of the 
            ## database, then build the appropriate 'field' object for each 
            ## one.
            ## First get the needed data out of the database
            ## Then build-up the fieldlists inside the field-sequences
            fields=[]
            for dummy, fieldlist in self.fieldlists:
                fk_fieldname = fieldlist.fk_fieldname
                model = fieldlist.model_class
                kwargs={fk_fieldname+'__exact': self.main_object}
                bits=model.objects.filter(**kwargs)
                
                for i, bit in enumerate(bits): 
                    for attr in fieldlist.template_field.widget.database_to_widget.keys():
                        value = bit.__getattribute__(attr)            
                        fieldname = fieldlist.base_name + '_%s' % (i+1)     
                        value_fieldname=fieldlist.template_field.widget.widget_to_database[fieldlist.template_field.widget.database_to_widget[attr]]
                        self.initial[value_fieldname % fieldname] = value                              

                how_many=len(self.get_names_from_datadict(fieldlist.base_name))
                fieldlist.build_fields(how_many)
                ## Also give each one a reference to the form  they are on, so
                ## that when they are needing to Bind, they can do so.
                fieldlist.set_form(self) 
                pluralised_fieldname = fieldlist.base_name + 's'
                self.__setattr__(pluralised_fieldname, fieldlist)        
            ## And then deal with getting them all into self.fields  
            self.put_fieldlists_into_form_fields()      
           

    def get_names_from_datadict(self, base_name):           
        """
        Return a list of the actual individual fieldnames by which all of the
        fields which are part of a field_array ... are known by in 
        self.fields by looking in self.data (or in self.initial)
        
        This will be something like 
        ['phone_1', 'phone_2'...'phone_N']
        
        """
        from sets import Set
        numbered_fields=[]    
        if self.data:
            data = self.data
        if self.initial:
            data = self.initial
            
        for name in data.keys():
            split_name = name.split('_')
            if (split_name[0] == base_name):
                fieldname = '_'.join( [split_name[0], split_name[1] ])
                numbered_fields.append(fieldname)       
        numbered_fields = Set(numbered_fields)
        ## Now phones should be something like just:
        ## ['repeating_phone_1', 'repeating_phone_2'] 
        return numbered_fields   
           
    def save_fieldlists(self): 
        for fieldlist in self.fieldlists:
            ## fieldlist wil be a tuple of (name, FieldList) ie
            ##('pets', <wjContact.contacts.views.fields.FieldList object at 0x0161CA50>)
            for field in self.__getattribute__(fieldlist[0]):
                ## items in self.pets are BoundFields - go inside them to
                ## access the actual original 'field'
                ## <wsl> FIXME
                if 'main_object' in self.__dict__:              
                    main_object_id = self.main_object.id
                else:
                    main_object_id = None
                field.field.widget.save_to_database(self.data, main_object_id, field.name)

class ContactForm(ExtensibleForm):
    """ """   
    
    klass = Contact # Experimental 
    ## Fields to go into the Contact table.
    first_name = forms.CharField(max_length=40, initial="New")
    last_name = forms.CharField(max_length=20, initial="Contact")
    address = forms.CharField(max_length=200, initial="17 Sunny Street")
    suburb = forms.CharField(max_length=40, initial="North Melbourne")
    state = forms.CharField(max_length=2, initial="Vi")
    country = forms.CharField(max_length=40, initial="Antarctica")
    email = forms.EmailField(initial="contact@place.org")
    date_added = forms.DateTimeField(initial=datetime.date.today())
   
    ## Fields to go into Phone table.
    # <wsl> Next lines - crufty. Remove later?
    PHONE_CHOICES = Phone.PHONE_CHOICES
    phones = FieldList(
        base_name='phone', 
        template_field=NewPhoneField(
                                widget=PhoneWidget(),
                                initial="new_entry#0411-222-333#mobile#",
                                 ), 
        fk_fieldname="contact", 
        model_class=NewPhone
        )

    def save(self):
        """ 
        Over-ride the save method to allow saving different fields to 
        different tables.
        """            
        ## First save contact-data into the Contact table  
        if self.stage_type == 'fresh_add' or self.stage_type == 'touched_add':
            contact = Contact(
                first_name=self.clean_data['first_name'],
                last_name=self.clean_data['last_name'],
                address=self.clean_data['address'],
                suburb=self.clean_data['suburb'], 
                state=self.clean_data['state'],
                country=self.clean_data['country'],
                email=self.clean_data['email'] ,
                date_added=self.clean_data['date_added'],
                )          
            contact.save()
                 
        elif self.stage_type == 'fresh_edit' or self.stage_type == 'touched_edit':             
            contact=self.main_object
            contact.first_name=self.clean_data['first_name']
            contact.last_name=self.clean_data['last_name']
            contact.address=self.clean_data['address']
            contact.suburb=self.clean_data['suburb'] 
            contact.state=self.clean_data['state']
            contact.country=self.clean_data['country']
            contact.email=self.clean_data['email'] 
            contact.date_added=self.clean_data['date_added']
            contact.save()
                           
        ## Now save repeating/multiple fields 
        ## <Wsl> FIXME 
        self.main_object = contact    
        self.save_fieldlists()      
        ## Now that we've saved all the appropriate data, return the new 
        ## owner object  - descendant classes may need it when they are going 
        ## through their own save() procedure. 
        return contact
     


               
class RecipientForm(ContactForm):
    """
    A form for displaying both contact fields and recipient fields with a 
    single 'submit' button.
    """
   
    ## We should already have all of the generic-contact fields since we
    ## will inherit them from ContactForm.   
    
    ## Make any last-minute alterations to the original Contact data here!
    ## In particular, we will re-define the 'initial' value for the last_name 
    ## field to be 'Recipient' rather than 'Contact'.
    last_name = forms.CharField(max_length=20, initial="Recipient") 

    ## The next fields are for details that relate specifically to 
    ## recipient-type contacts  - ie data which is to be stored in the 
    ## Recipient table.
    
    ## Grab in the list of concession types used as choices for this field
    ## by the Recipient form.
    CONCESSION_CHOICES = Recipient.CONCESSION_TYPES
    INTERNET_TYPES = Recipient.INTERNET_TYPES
    ## And here are the felds.
    concession_type = forms.ChoiceField(choices=CONCESSION_CHOICES, initial="other")
    concession_checked_by = forms.ModelChoiceField(Volunteer.objects.all(), initial=1)
    referring_org = forms.ModelChoiceField(Group.objects.all())
    install_windows = forms.BooleanField(initial=False, required=False)
    stay_with_linux = forms.BooleanField(initial=True, required=False)  
    survey_contact = forms.BooleanField(initial=True, required=False)  
    have_not_used_a_computer = forms.BooleanField(initial=False, required=False)
    can_type_documents = forms.BooleanField(initial=True, required=False)
    can_use_keyboard_and_mouse = forms.BooleanField(initial=True, required=False)
    can_use_email = forms.BooleanField(initial=True, required=False)
    can_use_internet = forms.BooleanField(initial=True, required=False)
    has_attended_training = forms.BooleanField(initial=False, required=False)
    internet_type = forms.ChoiceField(choices=INTERNET_TYPES, initial="none")
    
    def save(self):
        """
        Over-ride our save method so that we can save fields to more than
        one table.
        """    
        ## We need to save stuff into two different database tables
        ## here. 
        ## First we call the 'save()' method we have inherited from ContactForm. 
        ## This will correctly save all the data which should go into the 
        ## Contact table.
        ## Then we deal with saving the extra data which should go into the
        ## Recipient table.
        related_contact = ContactForm.save(self)
        # Now save the recipient-specific details into the recipient table,
        # and set the 'contact' to be the contact we just created.
        if self.stage_type == 'fresh_add' or self.stage_type == 'touched_add':      
            recipient = Recipient(contact=related_contact,
                concession_type = self.clean_data['concession_type'],
                concession_checked_by = self.clean_data['concession_checked_by'],
                referring_org = self.clean_data['referring_org'],
                install_windows = self.clean_data['install_windows'],
                stay_with_linux = self.clean_data['stay_with_linux'],
                survey_contact = self.clean_data['survey_contact'],
                have_not_used_a_computer = self.clean_data['have_not_used_a_computer'],
                can_type_documents = self.clean_data['can_type_documents'],
                can_use_keyboard_and_mouse = self.clean_data['can_use_keyboard_and_mouse'],
                can_use_email = self.clean_data['can_use_email'],
                can_use_internet = self.clean_data['can_use_internet'],
                has_attended_training = self.clean_data['has_attended_training'],
                internet_type = self.clean_data['internet_type'],)
            recipient.save()
            
                 
        elif self.stage_type == 'fresh_edit' or self.stage_type == 'touched_edit':             
            recipient=self.main_object
            recipient.contact=related_contact,
            recipient.concession_type = self.clean_data['concession_type']
            recipient.concession_checked_by = self.clean_data['concession_checked_by']
            recipient.referring_org = self.clean_data['referring_org']
            recipient.install_windows = self.clean_data['install_windows']
            recipient.stay_with_linux = self.clean_data['stay_with_linux']
            recipient.survey_contact = self.clean_data['survey_contact']
            recipient.have_not_used_a_computer = self.clean_data['have_not_used_a_computer']
            recipient.can_type_documents = self.clean_data['can_type_documents']
            recipient.can_use_keyboard_and_mouse = self.clean_data['can_use_keyboard_and_mouse']
            recipient.can_use_email = self.clean_data['can_use_email']
            recipient.can_use_internet = self.clean_data['can_use_internet']
            recipient.has_attended_training = self.clean_data['has_attended_training']
            recipient.internet_type = self.clean_data['internet_type']
            recipient.save()
                                 
        ## Now save repeating/multiple fields 
        ## <Wsl> FIXME 
        ## I think that self.main_object should always be contact, not recipient 
        ## etc. See ie save_fieldlists method for why!
        self.main_object = recipient    
        self.save_fieldlists()      
        ## Now that we've saved all the appropriate data, return the new 
        ## recipient object  - descendant classes may need it when they are going 
        ## through their own save() procedure. 
        return recipient
     
        
class not_VolunteerForm(ContactForm):
    """
    A form for displaying both contact fields and volunteer fields with a 
    single 'submit' button.
    """
   
    ## We should already have all of the generic-contact fields since we
    ## will inherit them from contactForm.   
    
    ## Make any last-minute alterations to the original Contact data here!
    ## In particular, we will re-define the last_name field to have an 
    ## initial value of 'Volunteer' rather than 'Contact'.
    last_name = forms.CharField(max_length=20, initial="Volunteer") 

    ## The next fields are for details that relate specifically to 
    ## volunteer-type contacts - ie data which is to be
    ## stored in the Volunteer table.
    
    ## Grab in the list of hours and interests used as choices for this field
    ## by the Volunteer form.
    HOURS_CHOICES = Volunteer.HOURS_CHOICES
    INTERESTS = Volunteer.INTERESTS
    ## And here are the fields
    hours = forms.ChoiceField(choices=HOURS_CHOICES, initial='monday_am')
    interests = forms.ChoiceField(choices=INTERESTS, initial='build_room')
    
    def save(self):
        """
        Over-ride our save method so that we can save fields to more than
        one table.
        """    
        ## We need to save stuff into two different database tables
        ## here. 
        ## First we call the 'save()' method we have inherited from ContactForm. 
        ## This will correctly save all the data which should go into the 
        ## Contact table, the Phone table, and the ContactPhone table.
        ## Then we deal with saving the extra data which should go into the
        ## Volunteer table.
        related_contact = VolunteerForm.save(self)
        # Now save the volunteer details into the Volunteer table,
        # and set the 'contact' to be the contact we just created.       
        new_volunteer = Volunteer(contact=related_contact,
            hours = self.clean_data['hours'],
            interests = self.clean_data['interests'],)
        new_volunteer.save()
        

##============================================================================##
class OwnerForm(ExtensibleForm):        

    """ """   
    ## Fields to go into the Owner table.
    first_name = forms.CharField(max_length=20, initial="New")
    last_name = forms.CharField(max_length=20, initial="Name")
    
    ## Fields to go into the Pet table.
    pets = FieldList(
        base_name='pet', 
        template_field=PetField(
                                widget=PetWidget(),
                                initial="new_entry#Jesse#False",
                                label="lovely pet #%s" % "new",
                                 ), 
        fk_fieldname="owner", 
        model_class=Pet
        )
                                                                       
    def save(self):
        """ 
        Over-ride the save method to allow saving different fields to 
        different tables. This specialised save() method saves owner-data into
        the Owner table, and  then calls save_pets() to save pet-data into the 
        Pet table. 
        """            

        ## First save owner-data into the Owner table  
        if self.stage_type == 'fresh_add' or self.stage_type == 'touched_add':
            owner = Owner(
                first_name=self.clean_data['first_name'],
                last_name=self.clean_data['last_name']
            )
            owner.save()
            
        
        elif self.stage_type == 'fresh_edit' or self.stage_type == 'touched_edit':     
            owner = self.main_object     
            owner.first_name=self.clean_data['first_name']
            owner.last_name=self.clean_data['last_name']
            owner.save()
                
            
        ## Now save repeating/multiple fields 
        ## <Wsl> FIXME 
        self.main_object = owner    
        self.save_fieldlists()      
        ## Now that we've saved all the appropriate data, return the new 
        ## owner object  - descendant classes may need it when they are going 
        ## through their own save() procedure. 
        return owner
     
 
##============================================================================## 

from wjContact.sales.models import Sale
from wjContact.computers.models import Computer
from wjContact.contacts.models import Recipient

#class SalesForm(ExtensibleForm):
class SalesForm(forms.Form):
    """ """   
    recipient = forms.IntegerField(label='', widget=forms.HiddenInput())
    computer = forms.CharField(label='cbv_no', max_length=20, initial="xxxx")

    def save(self):
#        pdb.set_trace()
        new_sale = Sale(computer=Computer(cbv_no=self.clean_data['computer']), 
            recipient=Recipient(id=self.clean_data['recipient']))
        new_sale.save()
        
        
from wjContact.sales.models import Sale
from wjContact.computers.models import Computer
from wjContact.contacts.models import Recipient

#class ComputerForm(ExtensibleForm):
class ComputerForm(forms.Form):
    """ """   

    cbv_no = forms.CharField(max_length=4, initial='1234')
    
    
    cpu_type = forms.ChoiceField(choices = Computer.CPU_TYPES)
    cpu_speed = forms.ChoiceField(choices = Computer.CPU_SPEEDS)
    case_type = forms.ChoiceField(choices = Computer.CASE_TYPES)
    ram = forms.ChoiceField(choices = Computer.RAM_AMOUNTS)
    hard_drive_size = forms.ChoiceField(choices = Computer.HARD_DRIVE_SIZES)
    optical_device1 = forms.CharField(max_length=50, initial='CD-Rom')
    optical_device2 = forms.CharField(max_length=50, initial='CD-RW') 
    monitor_type = forms.CharField(max_length=50, initial='CRT')
    monitor_size = forms.CharField(max_length=50, initial='17')  
    modem_type = forms.CharField(max_length=50, initial='Standard')
    usb = forms.CharField(max_length=50, initial='USB2.0')
    usb_ports = forms.CharField(max_length=50, initial='2')
    distroversion = forms.CharField(max_length=50, initial='CBV Standard')  
    computer_status = forms.ChoiceField(choices = Computer.STATUS_CHOICES, 
        initial = "in_shop")
      

    def save(self):
#        pdb.set_trace()
        new_computer = Computer(
            cpu_type = self.clean_data['cpu_type'],
            cpu_speed = self.clean_data['cpu_speed'],
            case_type = self.clean_data['case_type'],
            ram = self.clean_data['ram'],
            hard_drive_size = self.clean_data['hard_drive_size'],
            optical_device1 = self.clean_data['optical_device1'],
            optical_device2 = self.clean_data['optical_device2'], 
            monitor_type = self.clean_data['monitor_type'],
            monitor_size = self.clean_data['monitor_size'],
            modem_type = self.clean_data['modem_type'],
            usb = self.clean_data['usb'],
            usb_ports = self.clean_data['usb_ports'],
            distroversion = self.clean_data['distroversion'],
            computer_status = self.clean_data['computer_status'],
            )
        new_computer.save()
        
#===============================================================================  
class VolunteerForm(ContactForm):
    """ """   
      
    ## Make any last-minute alterations to the original Contact data here!
    ## In particular, we will re-define the 'initial' value for the last_name 
    ## field to be 'Volunteer' rather than 'Contact'.
    last_name = forms.CharField(max_length=20, initial="Volunteer") 
      
    ## And now add the fields specific to Volunteers  
    hours = forms.ChoiceField(choices=Volunteer.HOURS_CHOICES)
    interests = forms.ChoiceField(choices=Volunteer.INTERESTS)
    
    def save(self):
        """ 
        Over-ride the save method to allow saving different fields to 
        different tables.
        """            
        ## First save contact-data into the Contact table 
        related_contact = ContactForm.save(self) 
        if self.stage_type == 'fresh_add' or self.stage_type == 'touched_add':
            ## We need to save stuff into two different database tables
            ## here. 
            ## First we call the 'save()' method we have inherited from 
            ## ContactForm. 
            ## This will correctly save all the data which should go into the 
            ## Contact table.
            ## Then we deal with saving the extra data which should go into the
            ## Volunteer table.
            
            ## Now save the volunteer-specific details into the recipient table,
            ## and set the 'contact' to be the contact we just created. 
            volunteer = Volunteer(
                 contact = related_contact,
                 hours = self.clean_data['hours'],
                 interests = self.clean_data['interests']   
                 )          
            volunteer.save()
                 
        elif self.stage_type == 'fresh_edit' or self.stage_type == 'touched_edit':             
            volunteer=self.main_object
            volunteer.contact=related_contact,
            volunteer.hours = self.clean_data['hours'],
            volunteer.interests = self.clean_data['interests']   
            volunteer.save()
                        
        ## Now save repeating/multiple fields 
        ## <Wsl> FIXME 
        self.main_object = volunteer  
        self.save_fieldlists()      
        ## Now that we've saved all the appropriate data, return the new 
        ## object  - descendant classes may need it when they are going 
        ## through their own save() procedure. 
        return volunteer
           
 
